package com.astrob.activitys;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.TextView;

import com.astrob.TileSource.GoogleSRMapsTileSource;
import com.astrob.model.Msg;
import com.astrob.nhcmap.R;
import com.astrob.tspant.PointE;
import com.astrob.tspant.PublicFun;
import com.astrob.tspant.Tsp;
import com.astrob.util.Utils;

import org.osmdroid.api.IGeoPoint;
import org.osmdroid.events.MapListener;
import org.osmdroid.events.ScrollEvent;
import org.osmdroid.events.ZoomEvent;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapController;
import org.osmdroid.views.MapView;
import org.osmdroid.views.Projection;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.Polyline;
import org.osmdroid.views.overlay.ScaleBarOverlay;
import org.osmdroid.views.overlay.compass.CompassOverlay;
import org.osmdroid.views.overlay.gestures.RotationGestureOverlay;
import org.osmdroid.views.overlay.simplefastpoint.LabelledGeoPoint;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class IndoorMapActivity extends Activity implements View.OnClickListener {

    private final String TAG = "IndoorMapActivity";

    public static Intent createIntent(Context context) {
        return new Intent(context, IndoorMapActivity.class);
    }

    private MapView mMapView;
    private CompassOverlay mCompassOverlay;
    private ScaleBarOverlay mScaleBarOverlay;
    private MapController mMapController;
    private RotationGestureOverlay mRotationGestureOverlay;
    private CustomPointOverlay mGisOverlay = null;

    private TextView tv_info;

    private GeoPoint _geopoint = new GeoPoint(39.986250, 116.400025);//北京

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.indoormap_activity);
        mMapView = (MapView) findViewById(R.id.mapView);

        //让瓦片适应不同像素密度
        mMapView.setTilesScaledToDpi(true);

        //添加比例尺
        mScaleBarOverlay = new ScaleBarOverlay(mMapView);
        mMapView.getOverlays().add(mScaleBarOverlay);
        mScaleBarOverlay.setAlignBottom(true);//底部显示
        mScaleBarOverlay.setLineWidth(1 * (getResources().getDisplayMetrics()).density);
        mScaleBarOverlay.setMaxLength(0.85f);

        mMapView.setMapListener(mapListener);
        mGisOverlay = new CustomPointOverlay();
        mMapView.getOverlays().add(mGisOverlay);

        mMapController = (MapController) mMapView.getController();//获取MapView控制器
        mMapView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);//关闭硬件加速(绘制轨迹时需要)
        mMapController.setCenter(_geopoint);//设置地图中心
        mMapView.setMaxZoomLevel(21);//22-1米
        mMapView.setMinZoomLevel(15);
        mMapController.setZoom(18);//设置缩放级别
        mMapView.setBuiltInZoomControls(true);//设置缩放按钮可见
        mMapView.setMultiTouchControls(true);//设置多指触控可用

        findViewById(R.id.tv_clear).setOnClickListener(this);
        findViewById(R.id.tv_backone).setOnClickListener(this);
        findViewById(R.id.tv_recalculate).setOnClickListener(this);

        tv_info = (TextView) findViewById(R.id.tv_info);

        if (_routeline == null) {
            _routeline = new Polyline();
            _routeline.setWidth(3);
            _routeline.setColor(0xFF1B7BCD);
        }

        //
        String str1 = "127.0.0.1:25412/getnotfake.act?";
        GoogleSRMapsTileSource googleSRMapsTileSource = new GoogleSRMapsTileSource("Google-SR", 3, 19, 256,
                ".png", new String[]{str1});
        mMapView.setTileSource(googleSRMapsTileSource);

        onClear();
//        testTSP();
    }

    MapListener mapListener = new MapListener() {
        @Override
        public boolean onScroll(ScrollEvent scrollEvent) {
            return false;
        }

        @Override
        public boolean onZoom(ZoomEvent zoomEvent) {
            return false;
        }

        @Override
        public void longPress(Point pt) {
            if (pt == null) {
                return;
            }
        }

        //双击
        @Override
        public void doubleClick(Point pt) {
            if (pt == null) {
                return;
            }
        }

        //单击 单击后
        @Override
        public void singleClick(Point pt) {
            if (pt == null) {
                return;
            }
            addOne(pt);

        }

        //移图后抬起
        @Override
        public void touchUp() {

        }

        //手指移动-切换到移图模式
        @Override
        public void moveMap() {

        }
    };

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            default:
                break;
            case R.id.tv_clear:
                onClear();
                break;
            case R.id.tv_backone:
                onBackOne();
                break;
            case R.id.tv_recalculate:
                onReCal();
                break;
        }
    }

    private void addOne(Point pt) {
        if (pt == null) {
            return;
        }

        IGeoPoint geoPoint = mMapView.getProjection().fromPixels(pt.x, pt.y);
        int size = _points.size();
        LabelledGeoPoint labelp = new LabelledGeoPoint(geoPoint.getLatitude(), geoPoint.getLongitude());
        labelp.setLabel(size + "");
        _points.add(labelp);

        refreshRoute();

    }

    private void refreshRoute() {
        if (_points == null) {
            return;
        }

        int size = _points.size();
        List<GeoPoint> points = new ArrayList<GeoPoint>();
        for (int i = 0; i < size; i++) {
            LabelledGeoPoint labelp = _points.get(i);
            points.add(new GeoPoint(labelp.getLatitude(), labelp.getLongitude()));
        }
        _routeline.setPoints(points);
        _routeline.setColor(0xFF1B7BCD);
        mMapView.invalidate();

        tv_info.setText("" + calculateLen(points));
    }

    double calculateLen(List<GeoPoint> points) {
        if (points == null || points.size() < 2) {
            return 0;
        }

        double distance = 0;
        for (int i = 1; i < points.size(); i++) {
            GeoPoint A = points.get(i - 1);
            GeoPoint B = points.get(i);
            double x = A.getLongitudeE6() - B.getLongitudeE6();
            double y = A.getLatitudeE6() - B.getLatitudeE6();
            double lenA2B = Math.sqrt(x * x + y * y);
            distance += lenA2B;
        }

        return distance;
    }

    private void onClear() {
        if (_points == null) {
            return;
        }
        _points.clear();
        LabelledGeoPoint labelp = new LabelledGeoPoint(_geopoint.getLatitude(), _geopoint.getLongitude());
        labelp.setLabel("0");
        _points.add(labelp);

        refreshRoute();
    }

    private void onBackOne() {
        if (_points == null) {
            return;
        }
        int size = _points.size();
        if (size > 1) {
            _points.remove(size - 1);
        }
        refreshRoute();
    }

    //求阶乘
    int getNFactorial(int n) {
        if (n == 0) {
            return 1;
        }
        int sum = 1;
        for (int i = 1; i <= n; i++) {
            sum = sum * i;
        }
        return sum;
    }

    ProgressDialog mPB;
    boolean _isDoing = false;
    String _Info = "";
    Polyline _routeline = null;
    List<LabelledGeoPoint> _points = new ArrayList<LabelledGeoPoint>();

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == Msg.SEARCHFINISH) {
                if (mPB != null) {
                    mPB.dismiss();
                    mPB = null;
                }
                _isDoing = false;
                tv_info.setText(_Info);
                mMapView.invalidate();
            }
        }

    };

    private final static Comparator<LabelledGeoPoint> labelledGeoPointFunc = new Comparator<LabelledGeoPoint>() {
        @Override
        public int compare(LabelledGeoPoint object1, LabelledGeoPoint object2) {
            int index1 = Integer.valueOf(object1.getLabel());
            int index2 = Integer.valueOf(object2.getLabel());
            return index1 - index2;
        }
    };

    private void onReCal() {
        if (_points == null || _isDoing) {
            return;
        }
        _isDoing = true;

        mPB = ProgressDialog.show(this, "正在搜索", "搜索中...");
        new Thread(new Runnable() {
            @Override
            public void run() {
                int size = _points.size();
                //坐标原点
                long centerX = _geopoint.getLongitudeE6();
                long centerY = _geopoint.getLatitudeE6();

                Collections.sort(_points, labelledGeoPointFunc);

                int kk = getNFactorial(size);
                PublicFun.getInstance().N_ANT_COUNT = 50;//蚂蚁数量 城市数的阶乘
                PublicFun.getInstance().N_IT_COUNT = 200;//迭代次数

                PublicFun.getInstance().cityList.clear();
                List<GeoPoint> points = new ArrayList<GeoPoint>();
                for (int i = 0; i < size; i++) {
                    LabelledGeoPoint labelp = _points.get(i);
                    points.add(new GeoPoint(labelp.getLatitude(), labelp.getLongitude()));
                    if (i == size - 1) {
                        PublicFun.getInstance().destCity = new PointE((long) labelp.getLongitudeE6(), (long) labelp.getLatitudeE6());
                    } else {
                        PublicFun.getInstance().cityList.add(new PointE((long) labelp.getLongitudeE6(), (long) labelp.getLatitudeE6()));
                    }
                }

                _points.clear();
                points.clear();

                String str = "";

                try {
                    Tsp tsp = new Tsp();
                    tsp.InitData();//开始执行

                    ArrayList<String> resultList = new ArrayList<String>();
                    for (int i = 0; i < tsp.m_betterAnts.size(); i++) {
                        str = tsp.getAntPath(tsp.m_betterAnts.get(i)) + "长度:" + tsp.getAntLength(tsp.m_betterAnts.get(i));
                        if (!resultList.contains(str)) {
                            resultList.add(str);
                        }
                    }
                    _Info = "长度: " + tsp.getAntLength(tsp.m_bestAnt) + " 路径: " + tsp.getAntPath(tsp.m_bestAnt);
                    size = tsp.m_bestAnt.m_nPath.length;
                    for (int i = 0; i < size; i++) {
                        int index = tsp.m_bestAnt.m_nPath[i];
                        PointE p = PublicFun.getInstance().cityList.get(index);
                        points.add(new GeoPoint((int) p.y, (int) p.x));
                        LabelledGeoPoint labelp = new LabelledGeoPoint((int) p.y, (int) p.x);
                        labelp.setLabel(index + "");
                        _points.add(labelp);
                    }

                    points.add(new GeoPoint((int) PublicFun.getInstance().destCity.y, (int) PublicFun.getInstance().destCity.x));
                    LabelledGeoPoint labelp = new LabelledGeoPoint((int) PublicFun.getInstance().destCity.y, (int) PublicFun.getInstance().destCity.x);
                    labelp.setLabel(size + "");
                    _points.add(labelp);

                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                }
                _routeline = new Polyline();
                _routeline.setWidth(3);
                _routeline.setPoints(points);
                _routeline.setColor(0xFFFF0000);

                mHandler.sendEmptyMessage(Msg.SEARCHFINISH);
            }
        }).start();

    }


    public class CustomPointOverlay extends Overlay {

        private final Point mMapCoordsProjected = new Point();

        public CustomPointOverlay() {
        }

        @Override
        public void draw(Canvas canvas, MapView mapView, boolean shadow) {

            Paint paint = new Paint();
            paint.reset();
            paint.setStrokeWidth(3);

            if (_routeline != null && _points != null) {
                _routeline.draw(canvas, mapView, shadow);

                paint.setStrokeWidth(8);
                paint.setTextSize(dip2px(16));

                int size = _points.size();
                for (int i = 0; i < size; ++i) {
                    LabelledGeoPoint lp = _points.get(i);
                    Point ff = LL2XY(lp);

                    if (i == 0) {
                        Bitmap bm = ((BitmapDrawable) getResources().getDrawable(R.drawable.map_marker3))
                                .getBitmap();
                        int x = (int) (ff.x - bm.getWidth() / 2);
                        int y = (int) (ff.y - bm.getHeight());
                        canvas.drawBitmap(bm, x, y, null);
                    } else if (i == size - 1) {
                        Bitmap bm = ((BitmapDrawable) getResources().getDrawable(R.drawable.map_marker2))
                                .getBitmap();
                        int x = (int) (ff.x - bm.getWidth() / 2);
                        int y = (int) (ff.y - bm.getHeight());
                        canvas.drawBitmap(bm, x, y, null);
                    } else {
                        paint.setColor(Color.parseColor("#AAAF0000"));
                        canvas.drawCircle(ff.x, ff.y, dip2px(12), paint);
                        String strPrn = lp.getLabel();
                        float textWidth = paint.measureText(strPrn) / 2;
                        float textHeight = paint.getTextSize() / 2;
                        paint.setColor(Color.WHITE);
                        canvas.drawText(strPrn, ff.x - textWidth, ff.y + textHeight - 1, paint);
                    }
                }
            }
        }

        Point LL2XY(GeoPoint g) {
            Point B = new Point();
            mMapView.getProjection().toProjectedPixels(g.getLatitude(),
                    g.getLongitude(), mMapCoordsProjected);
            Projection pj = mMapView.getProjection();
            pj.toPixelsFromProjected(mMapCoordsProjected, B);
            return B;
        }
    }

    int dip2px(int dip) {
        return Utils.dip2px(this, dip);
    }

    private void testTSP() {
        PublicFun.getInstance().N_ANT_COUNT = 50;//蚂蚁数量
        PublicFun.getInstance().N_IT_COUNT = 1;//迭代次数

        long centerX = _geopoint.getLongitudeE6();
        long centerY = _geopoint.getLatitudeE6();

        PublicFun.getInstance().cityList.add(new PointE(centerX + 0, centerY + 0));//A
        PublicFun.getInstance().cityList.add(new PointE(centerX + 100, centerY + 10));//B
        PublicFun.getInstance().cityList.add(new PointE(centerX + 20, centerY - 100));//C
        PublicFun.getInstance().cityList.add(new PointE(centerX + 100, centerY - 200));//D
        PublicFun.getInstance().cityList.add(new PointE(centerX - 100, centerY - 100));//E
        PublicFun.getInstance().destCity = new PointE(centerX - 300, centerY - 200);

        _points.clear();
        List<GeoPoint> points = new ArrayList<GeoPoint>();

        try {
            Tsp tsp = new Tsp();
            tsp.InitData();//开始执行

            ArrayList<String> resultList = new ArrayList<String>();
            for (int i = 0; i < tsp.m_betterAnts.size(); i++) {
                String str = tsp.getAntPath(tsp.m_betterAnts.get(i)) + "长度:" + tsp.getAntLength(tsp.m_betterAnts.get(i));
                if (!resultList.contains(str)) {
                    resultList.add(str);
                }
            }
            String str = "路径:" + tsp.getAntPath(tsp.m_bestAnt) + "长度:" + tsp.getAntLength(tsp.m_bestAnt);
            int size = tsp.m_bestAnt.m_nPath.length;
            for (int i = 0; i < size; i++) {
                int index = tsp.m_bestAnt.m_nPath[i];
                PointE p = PublicFun.getInstance().cityList.get(index);
                points.add(new GeoPoint((int) p.y, (int) p.x));
                LabelledGeoPoint labelp = new LabelledGeoPoint((int) p.y, (int) p.x);
                labelp.setLabel(index + "");
                _points.add(labelp);
            }

            points.add(new GeoPoint((int) PublicFun.getInstance().destCity.y, (int) PublicFun.getInstance().destCity.x));
            LabelledGeoPoint labelp = new LabelledGeoPoint((int) PublicFun.getInstance().destCity.y, (int) PublicFun.getInstance().destCity.x);
            labelp.setLabel("Dest");
            _points.add(labelp);

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        if (points.size() > 2) {
            _routeline.setPoints(points);
        }
    }

}
